package com.yunkeji.utils;

import com.yunkeji.common.constant.CacheConstants;
import com.yunkeji.common.constant.LuaScriptConsts;
import com.yunkeji.common.utils.redis.RedisUtils;
import lombok.Builder;
import lombok.Data;
import lombok.ToString;
import org.redisson.api.RScript;
import org.redisson.client.codec.LongCodec;

import java.util.Arrays;
import java.util.List;

/**
 * 通话计费
 *
 * @author 老张
 */
public class CallCountUtils {

    /**
     * 根据ucid查询并更新通话信息
     * 此方法通过执行Redis脚本，来获取并计算特定ucid的通话详情，包括是否免费、通话心跳次数以及计费次数
     *
     * @param ucid 通话唯一标识
     * @return 返回包含是否免费、计费次数和通话心跳次数的CallInfo对象
     */
    public static CallInfo callCaount(String ucid) {
        // 获取Redis脚本客户端
        RScript rScript = RedisUtils.getClient().getScript(LongCodec.INSTANCE);
        // 执行Redis脚本，并获取包含通话信息的结果列表
        List<Object> result =
                rScript.eval(
                        RScript.Mode.READ_WRITE, // 以读写模式执行脚本
                        LuaScriptConsts.BILL_SCRIPT, // 执行预定义的Lua脚本
                        RScript.ReturnType.MULTI, // 返回多个结果
                        // 键列表，用于在脚本中操作对应的Redis键
                        Arrays.asList(
                                CacheConstants.CALL_BILL_UPDATE + ucid, // 本次通话是否计费的键
                                // 通话心跳次数键（包含主叫和被叫）
                                CacheConstants.CALL_KEEP_LIVE_TIMES_UPDATE + ucid,
                                // 计费总次数键
                                CacheConstants.CALL_PRICE_TIMES_UPDATE + ucid),
                        2, // 脚本中用于读写操作的键的数量
                        70000); // 脚本执行的超时时间（毫秒）

        // 本次是否需要计费，通过判断结果列表的第一个元素是否为"1"来决定
        Boolean freeFlag = "1".equals(String.valueOf(result.get(0)));
        // 通话心跳次数(包含主叫和被叫)，从结果列表的第二个元素获取
        Integer keepLiveTimes = Integer.valueOf(String.valueOf(result.get(1)));
        // 计费总次数=通话心跳次数/2，从结果列表的第三个元素获取，若为空则默认为0
        Integer priceTimes =
                Integer.valueOf(result.get(2) == null ? "0" : String.valueOf(result.get(2)));

        // 构建并返回CallInfo对象，包含是否免费、计费次数和通话心跳次数
        return CallInfo.builder()
                .freeFlag(freeFlag)
                .priceTimes(priceTimes)
                .keepLiveTimes(keepLiveTimes)
                .build();
    }

    @Data
    @Builder
    @ToString
    public static class CallInfo {
        // 本次是否需要计费
        Boolean freeFlag;
        // 通话心跳次数(包含主叫和被叫)
        Integer keepLiveTimes;
        // 计费总次数=通话心跳次数/2
        Integer priceTimes;
    }
}
